package m.html.util;

import com.alibaba.fastjson.JSONObject;
import m.html.element.Button;
import m.html.element.Element;
import m.html.element.Text;
import m.html.element.attr.ButtonType;
import m.html.element.other.DisplayItem;
import m.system.exception.MException;
import m.system.util.*;
import manage.util.DictionaryUtil;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.*;

public class EchartsUtil {
    public static <T extends IVueListColumn> Element toPopoverContent(List<T> cols) {
        try {
            Element xElement=Element.tag("a-flex").A("wrap","wrap").A("gap","small");
            Element yElement=Element.tag("a-flex").A("wrap","wrap").A("gap","small");
            for (IVueListColumn col : cols) {
                if(col.getType().equals("index")) continue;
                if(col.isFalse()) continue;
                String gt=null!=col.getGroupTitle()&&col.getGroupTitle().length>0?ArrayUtil.connection(col.getGroupTitle(),",")+"-":"";
                if(StringUtil.isSpace(col.getNumberFormat())){
                    xElement.E(Element.tag("a-checkbox").A("value",col.getFieldAs()).E(new Text(gt+col.getTitle())));
                }else{
                    yElement.E(Element.tag("a-checkbox").A("value",col.getFieldAs()).E(new Text(gt+col.getTitle())));
                }
            }
            Element listElement = Element.tag("a-list").A("size", "small").A("style", "max-height:300px;overflow-y:auto;");
            listElement.E(
                Element.tag("a-list-item")
                .E(
                    Element.tag("a-radio-group").A("button-style","solid").A("optionType","button")
                    .A("v-model:value","searchParams['echarts_type']")
                    .A(":options","searchParams['echarts_options']")
                ),
                Element.tag("a-list-item")
                .E(
                    Element.tag("a-list-item-meta")
                    .E(
                        Element.tag("template").A("#avatar")
                        .E(new Text("维度"))
                    ),
                    Element.tag("div").A("style", "flex:5;")
                    .E(
                        Element.tag("a-checkbox-group")
                        .A("v-model:value", "searchParams['echarts_x']")
                        .E(xElement)
                    )
                ),
                Element.tag("a-list-item")
                .E(
                    Element.tag("a-list-item-meta")
                    .E(
                        Element.tag("template").A("#avatar")
                        .E(new Text("数据{{searchParams['echarts_type'].indexOf('+')>0?'(左)':''}}"))
                    ),
                    Element.tag("div").A("style", "flex:5;")
                    .E(
                        Element.tag("a-checkbox-group")
                        .A("v-model:value", "searchParams['echarts_y']")
                        .E(yElement)
                    )
                ),
                Element.tag("a-list-item").A("v-if","searchParams['echarts_type'].indexOf('+')>0")
                .E(
                    Element.tag("a-list-item-meta")
                    .E(
                        Element.tag("template").A("#avatar")
                        .E(new Text("数据(右)"))
                    ),
                    Element.tag("div").A("style", "flex:5;")
                    .E(
                        Element.tag("a-checkbox-group")
                        .A("v-model:value", "searchParams['echarts_y_right']")
                        .E(yElement)
                    )
                )
            );
            return Element.tag("div").A("style", "width:500px;margin:-10px -10px 0;").E(
                listElement,
                Element.tag("div").A("style","padding-top:8px;text-align:center;border-top: 1px solid #8884;")
                .E(
                    Element.tag("a-space")
                    .E(
                        new Button(ButtonType.PRIMARY).A("size", "small").A("style", "width:100px;").E(new Text("图表查询")).setExtend(" @click=\"toEchartsPage();\" ")
                    )
                )

            );
        }catch (Exception e){
            return Element.tag("div").E(new Text(e.getMessage()));
        }
    }
    public static <T extends IVueListColumn> JSONMessage toEchartsOption(String title, List<T> cols, List<?> list, String[] ps, boolean simple) throws MException, ClassNotFoundException {
        String type=StringUtil.noSpace(ps[0],"line");
        String[] xfields=stringToArray(ps[1]);
        String[] y1fields=stringToArray(ps[2]);
        String[] y2fields=stringToArray(ps[3]);
        if("pie".equals(type)){
            return toPieEchartsOption(title,cols,list,xfields,y1fields,simple);
        }else{
            return toLineEchartsOption(title,cols,list,xfields,y1fields,y2fields,type,simple);
        }
    }
    private static String[] stringToArray(String str){
        if(StringUtil.isSpace(str)||"[]".equals(str)) return new String[0];
        return str.replaceAll("\\[","").replaceAll("]","").replaceAll("\"","").split(",");
    }
    private static <T extends IVueListColumn> String getColName(List<T> cols,String field){
        for(T col : cols) {
            if (col.getFieldAs().equals(field)) {
                return (null != col.getGroupTitle() && col.getGroupTitle().length > 0 ? (ArrayUtil.connection(col.getGroupTitle(), ",")+"-") : "")+col.getTitle();
            }
        }
        return "";
    }
    private static <T extends IVueListColumn> JSONMessage toPieEchartsOption(String title, List<T> cols, List<?> list, String[] xfields,String[] yfields, boolean simple) throws MException, ClassNotFoundException {

        Map<String,List<DisplayItem>> disMap= new HashMap<>();
        Map<String,String> dfMap= new HashMap<>();
        Map<String,String> dtMap= new HashMap<>();
        for(String xf : xfields) {
            for (T col : cols) {
                if(col.getFieldAs().equals(xf)){
                    disMap.put(xf,col.getDisItems());
                    dfMap.put(xf,col.getDateFormat());
                    dtMap.put(xf,col.getDictType());
                }
            }
        }
//        JSONMessage[] series=getSeries(yfields,cols);
        List<String> xAxisList= new ArrayList<>();
        Map<String,Double[]> dataMap=new HashMap<>();
        Double[] sums=new Double[yfields.length];
        for(Object data : list){
            StringBuilder txt= new StringBuilder();
            for(String xf : xfields){
                Object content= ActionUtil.getInAttribute(data, xf);
                String tmp;
                if(null==content){
                    tmp="";
                }else if(content instanceof Object[]){
                    tmp=ArrayUtil.connection((Object[])content,",");
                }else{
                    tmp=content.toString();
                }
                if(!StringUtil.isSpace(tmp)) {
                    if(!StringUtil.isSpace(dfMap.get(xf))) {
                        Date date;
                        if(content instanceof LocalDateTime){
                            Instant instant = ((LocalDateTime)content).atZone(ZoneId.systemDefault()).toInstant();
                            date=Date.from(instant);
                        }else{
                            date=(Date)content;
                        }
                        txt.append(DateUtil.format(date, dfMap.get(xf)));
                    }else if(!StringUtil.isSpace(dtMap.get(xf))) {
                        txt.append(DictionaryUtil.getName(dtMap.get(xf), content));
                    }else{
                        StringBuilder tt=new StringBuilder();
                        List<DisplayItem> items=disMap.get(xf);
                        if(items.isEmpty()) tt.append(tmp);
                        else{
                            List<String> arr= new ArrayList<>();
                            if(content instanceof String[]) {
                                arr.addAll(Arrays.asList((String[]) content));
                            }else{
                                arr.add(tmp);
                            }
                            for(int n=0;n<arr.size();n++){
                                if(n>0) tt.append(",");
                                for(DisplayItem item : items) {
                                    if(StringUtil.noSpace(item.getValue()).equals(arr.get(n))) {
                                        tt.append(item.getTitle());
                                    }
                                }
                            }
                        }
                        txt.append(tt);
                    }
                }
            }
            String fn=txt.toString();
            if(!xAxisList.contains(fn)){
                xAxisList.add(fn);
                dataMap.put(fn,new Double[yfields.length]);
            }
            for(int i=0;i<yfields.length;i++){
                Object content= ActionUtil.getInAttribute(data, yfields[i]);
                String tmp=null==content?"":content.toString();
                double d=0D;
                if(!StringUtil.isSpace(tmp)) {
                    d=Double.parseDouble(tmp);
                }
                Double[] nums=dataMap.get(fn);
                if(null==nums[i]) nums[i]=d;
                else nums[i]=NumberUtil.round(nums[i]+d,2);
                if(null==sums[i]) sums[i]=d;
                else sums[i]=NumberUtil.round(sums[i]+d,2);
            }
        }
        List<Object[]> source=new ArrayList<>();
        Object[] ts=new Object[yfields.length+1];
        ts[0]="field";
        for(int i=0;i<yfields.length;i++) ts[i+1]=yfields[i]+"_sum";
        source.add(ArrayUtil.concat(ts,yfields));
        for(String fn : dataMap.keySet()){
            Object[] vs=new Object[yfields.length+1];
            vs[0]=fn;
            Double[] vd=dataMap.get(fn);
            for(int i=0;i<vd.length;i++){
                vs[i+1]=NumberUtil.round(vd[i]/sums[i]*100.0,1);
            }
            source.add(ArrayUtil.concat(vs,dataMap.get(fn)));
        }
        List<JSONMessage> titles=new ArrayList<>();
        titles.add(new JSONMessage()
            .push("text",title)
            .push("top","15px")
            .push("left","15px")
            .push("textStyle",new JSONMessage()
                .push("fontSize",16)
                .push("fontWeight","normal")
            )
        );
        List<JSONMessage> series=new ArrayList<>();
        String[] radius=yfields.length==1?new String[]{"40%","80%"}:(yfields.length==2?new String[]{"30%","70%"}:new String[]{"25%","60%"});
        String[] center=yfields.length==1?new String[]{"50%"}:(yfields.length==2?new String[]{"27%","73%"}:new String[]{"19%","50%","81%"});
        for(int i=0;i<yfields.length;i++){
            String y=yfields[i];
            series.add(new JSONMessage()
                .push("name",getColName(cols,y))
                .push("type","pie")
                .push("radius",radius)
                .push("center",new String[]{center[i],simple?"50%":"54%"})
                .push("smooth",true)
                .push("encode",
                    new JSONMessage()
                    .push("itemName","field")
                    .push("value",y)
                )
                .push("label",
                    new JSONMessage()
                    .push("position","inner")
                    .push("formatter","{@field}\n{@"+y+"_sum}%")
                )
                .push("itemStyle",
                    new JSONMessage()
                    .push("borderRadius",10)
                    .push("borderColor","#f9f9f9")
                    .push("borderWidth",5)
                )
            );
            titles.add(
                new JSONMessage()
                .push("subtext",getColName(cols,y))
                .push("left",center[i])
                .push("bottom",simple?"48%":"44%")
                .push("textAlign","center")
            );
        }
        JSONMessage json=new JSONMessage();
        if(!simple){
            json.push("title",titles);
            json.push("legend",new JSONMessage().push("top","40px").push("left","20px"));
            json.push("toolbox",new JSONMessage()
                .push("top","15px")
                .push("right","90px")
                .push("feature",new JSONMessage()
                    .push("restore",new JSONMessage())
                    .push("saveAsImage",new JSONMessage())
                )
            );
        }else{
        }
        json.push("dataset",new JSONMessage[]{
            new JSONMessage().push("source",source)
        });
        json.push("series",series);
        json.push("tooltip",new JSONMessage()
            .push("trigger","item")
        );
        return json;
    }

    private static <T extends IVueListColumn> JSONMessage toLineEchartsOption(String title, List<T> cols, List<?> list, String[] xfields,String[] y1fields,String[] y2fields,String types, boolean simple) throws MException, ClassNotFoundException {
        String[] type=types.split("\\+");
        List<JSONMessage> yAxisList= new ArrayList<>();
        yAxisList.add(new JSONMessage().push("type","value").push("splitLine",false));
        if(type.length>1) yAxisList.add(new JSONMessage().push("type","value").push("splitLine",false));
        Map<String,List<DisplayItem>> disMap= new HashMap<>();
        Map<String,String> dfMap= new HashMap<>();
        Map<String,String> dtMap= new HashMap<>();
        for(String xf : xfields) {
            for (T col : cols) {
                if(col.getFieldAs().equals(xf)){
                    disMap.put(xf,col.getDisItems());
                    dfMap.put(xf,col.getDateFormat());
                    dtMap.put(xf,col.getDictType());
                }
            }
        }
        JSONMessage[] series=getSeries(type,y1fields,y2fields,cols);
        List<String> xAxisList= new ArrayList<>();
        for(Object data : list){
            StringBuilder txt= new StringBuilder();
            for(String xf : xfields){
                Object content= ActionUtil.getInAttribute(data, xf);
                String tmp;
                if(null==content){
                    tmp="";
                }else if(content instanceof Object[]){
                    tmp=ArrayUtil.connection((Object[])content,",");
                }else{
                    tmp=content.toString();
                }
                if(!StringUtil.isSpace(tmp)) {
                    if(!StringUtil.isSpace(dfMap.get(xf))) {
                        Date date;
                        if(content instanceof LocalDateTime){
                            Instant instant = ((LocalDateTime)content).atZone(ZoneId.systemDefault()).toInstant();
                            date=Date.from(instant);
                        }else{
                            date=(Date)content;
                        }
                        txt.append(DateUtil.format(date, dfMap.get(xf)));
                    }else if(!StringUtil.isSpace(dtMap.get(xf))) {
                        txt.append(DictionaryUtil.getName(dtMap.get(xf), content));
                    }else{
                        StringBuilder tt=new StringBuilder();
                        List<DisplayItem> items=disMap.get(xf);
                        if(items.isEmpty()) tt.append(tmp);
                        else{
                            List<String> arr= new ArrayList<>();
                            if(content instanceof String[]) {
                                arr.addAll(Arrays.asList((String[]) content));
                            }else{
                                arr.add(tmp);
                            }
                            for(int n=0;n<arr.size();n++){
                                if(n>0) tt.append(",");
                                for(DisplayItem item : items) {
                                    if(StringUtil.noSpace(item.getValue()).equals(arr.get(n))) {
                                        tt.append(item.getTitle());
                                    }
                                }
                            }
                        }
                        txt.append(tt);
                    }
                }
            }
            if(!xAxisList.contains(txt.toString())){
                xAxisList.add(txt.toString());
            }
            int n=xAxisList.indexOf(txt.toString());
            for(JSONMessage serie:series){
                List<Double> ds= (List<Double>) serie.get("data");
                Object content= ActionUtil.getInAttribute(data, serie.get(String.class,"field"));
                String tmp=null==content?"":content.toString();
                double d=0D;
                if(!StringUtil.isSpace(tmp)) {
                    d=Double.parseDouble(tmp);
                }
                if(ds.size()<=n){
                    ds.add(NumberUtil.round(d));
                }else{
                    ds.set(n,NumberUtil.round(ds.get(n)+d,2));
                }
            }
        }
        List<String> legendList= new ArrayList<>();
        for(JSONMessage json : series){
            legendList.add(json.get(String.class,"name"));
        }
        JSONMessage xAxis=new JSONMessage().push("type","category").push("data",xAxisList);
        JSONMessage json=new JSONMessage();
        if(!simple){
            json.push("title",new JSONMessage()
                .push("text",title)
                .push("top","15px")
                .push("left","15px")
                .push("textStyle",new JSONMessage()
                    .push("fontSize",16)
                    .push("fontWeight","normal")
                )
            );
            json.push("dataZoom",new JSONMessage[]{new JSONMessage()});
            json.push("toolbox",new JSONMessage()
                .push("top","15px")
                .push("right","80px")
                .push("feature",new JSONMessage()
                    .push("magicType",new JSONMessage()
                        .push("type",new String[]{"line","bar","stack","tiled"})
                    )
                    .push("restore",new JSONMessage())
                    .push("saveAsImage",new JSONMessage())
                )
            );
            json.push("legend",new JSONMessage().push("data",legendList).push("top","15px"));
            json.push("grid",new JSONMessage()
                .push("top","90px")
                .push("left","15px")
                .push("right","15px")
                .push("bottom","55px")
                .push("containLabel",true)
            );
        }else{
            json.push("grid",new JSONMessage()
                .push("top","3px")
                .push("left","-15px")
                .push("right","-3px")
                .push("bottom","1px")
                .push("containLabel",true)
            );
            for(JSONMessage y : yAxisList){
                y.push("show",false);
            }
            xAxis.push("show",false);
        }
        json.push("yAxis",yAxisList.toArray(new JSONMessage[]{}));
        json.push("xAxis",xAxis);
        json.push("series",series);
        json.push("tooltip",new JSONMessage()
            .push("trigger","axis")
        );
        return json;
    }
    private static <T extends IVueListColumn> JSONMessage[] getSeries(String[] type,String[] y1fields,String[] y2fields, List<T> cols){
        List<JSONMessage> jsons= new ArrayList<>();
        for(String y1f : y1fields){
            for(T col : cols){
                if(col.getFieldAs().equals(y1f)){
                    String gt=null!=col.getGroupTitle()&&col.getGroupTitle().length>0?(ArrayUtil.connection(col.getGroupTitle(),",")+"-"):"";
                    jsons.add(new JSONMessage()
                        .push("field",y1f)
                        .push("name",gt+col.getTitle())
                        .push("data",new ArrayList<Double>())
                        .push("type",type[0])
                        .push("smooth",true)
                        .push("itemStyle",new JSONMessage().push("borderRadius",new Integer[]{6,6,0,0}))
                    );
                }
            }
        }
        if(type.length>1){
            for(String y2f : y2fields){
                for(T col : cols){
                    if(col.getFieldAs().equals(y2f)){
                        String gt=null!=col.getGroupTitle()&&col.getGroupTitle().length>0?(ArrayUtil.connection(col.getGroupTitle(),",")+"-"):"";
                        jsons.add(new JSONMessage()
                            .push("field",y2f)
                            .push("name",gt+col.getTitle())
                            .push("data",new ArrayList<Double>())
                            .push("type",type[1])
                            .push("smooth",true)
                            .push("yAxisIndex",1)
                            .push("itemStyle",new JSONMessage().push("borderRadius",new Integer[]{6,6,0,0}))
                        );
                    }
                }
            }
        }
        return jsons.toArray(new JSONMessage[]{});
    }
}
